package xyz.iguilty.workflow.example.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
import org.flowable.bpmn.constants.BpmnXMLConstants;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.persistence.entity.HistoricProcessInstanceEntityImpl;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.idm.api.Group;
import org.flowable.idm.api.User;
import org.flowable.image.impl.DefaultProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import xyz.iguilty.workflow.example.entity.Leave;
import xyz.iguilty.workflow.example.temp.HistoryInfo;
import xyz.iguilty.workflow.example.temp.Resolve;
import xyz.iguilty.workflow.example.temp.TaskTest;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/leave")
@Api(tags = "请假流程")
public class LeaveController {
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private IdentityService identityService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private RepositoryService repositoryService;

    @ApiOperation(value = "创建流程")
    @PostMapping(value = "/start")
    public String start(Leave leave) {
        Integer days = leave.getDays();
        if (days ==null){
            throw new IllegalArgumentException();
        }
        Map<String,Object> variables = new HashMap<>();
        String businessKey = String.format("business:%s", UUID.randomUUID());
        variables.put("initiator", "");
        variables.put("_FLOWABLE_SKIP_EXPRESSION_ENABLED", true);
        variables.put("days", days);
        variables.put("workflow_example_leave_initiate_candidateUser",leave.getApplicant());
        if (days<=3){
            variables.put("workflow_example_leave_leaderAudit_candidateUser","leader");
        }else {
            List<String> nextActors = new ArrayList<>();
            nextActors.add("hr");
            nextActors.add("hr2");
            nextActors.add("hr3");
            nextActors.add("hr4");
            nextActors.add("hr5");
            nextActors.add("hr6");
            variables.put("workflow_example_leave_hrAudit_candidateUsers",nextActors);
        }
        identityService.setAuthenticatedUserId(leave.getApplicant());//设置流程发起人
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(Leave.PROCESS_DEFINITION_KEY,businessKey, variables);
        return String.format("ok %s",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }

    @ApiOperation(value = "查看任务")
    @GetMapping("/tasks")
    public List<TaskTest> getTasks(@RequestParam String candidateUser) {
        List<Task> list = taskService.createTaskQuery().processDefinitionKey(Leave.PROCESS_DEFINITION_KEY).taskCandidateUser(candidateUser).list();

        return list.stream().map(task -> {
            TaskTest taskInfo = new TaskTest();
            taskInfo.setTaskId(task.getId());
            taskInfo.setCurrentActivity(task.getTaskDefinitionKey());
            taskInfo.setTaskName(task.getName());
            taskInfo.setTaskDescription(task.getDescription());
            taskInfo.setProcessInstanceId(task.getProcessInstanceId());
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            taskInfo.setBusinessKey(processInstance.getBusinessKey());
            taskInfo.setClaimTime(task.getClaimTime());
            taskInfo.setCreateTime(task.getCreateTime());
            return taskInfo;
        }).collect(Collectors.toList());
    }

    @ApiOperation(value = "查看详情")
    @GetMapping(value = "/detail")
    public List<Comment> detail(String businessKey) {
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey).singleResult();
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().processInstanceId(historicProcessInstance.getId()).list();
        List<Comment> result = new ArrayList<>();
        for (HistoricTaskInstance taskInstance:list){
            List<Comment> taskComments = taskService.getTaskComments(taskInstance.getId());
            result.addAll(taskComments);
        }
        return result;
    }

    @ApiOperation(value = "我发起的")
    @GetMapping("/iStart")
    public List<HistoryInfo> iStart(@RequestParam String userId) {
        List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery()
                .startedBy(userId)
                .orderByProcessInstanceStartTime()
                .desc()
                .list();
        return list.stream().map(history -> {
            HistoryInfo historyInfo = new HistoryInfo();
            historyInfo.setHistoryId(history.getId());
            historyInfo.setBusinessKey(history.getBusinessKey());
            historyInfo.setProcessDefinitionName(history.getProcessDefinitionName());
            historyInfo.setProcessDefinitionKey(history.getProcessDefinitionKey());
            historyInfo.setStartTime(history.getStartTime());
            historyInfo.setEndTime(history.getEndTime());
            historyInfo.setStarterId(history.getStartUserId());
            historyInfo.setDeleteReason(history.getDeleteReason());
            historyInfo.setName(history.getName());
            historyInfo.setProcessInstanceId(((HistoricProcessInstanceEntityImpl) history).getProcessInstanceId());
            return historyInfo;
        }).collect(Collectors.toList());
    }

    @ApiOperation(value = "我处理过的")
    @GetMapping("/iResolved")
    public List<TaskTest> iResolved(@RequestParam String userId) {
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().taskAssignee(userId).finished().list();
        List<TaskTest> taskInfos = list.stream().map(instance -> {
            TaskTest taskInfo = new TaskTest();
            taskInfo.setCurrentActivity(instance.getTaskDefinitionKey());
            taskInfo.setTaskName(instance.getName());
            taskInfo.setTaskDescription(instance.getDescription());
            taskInfo.setProcessInstanceId(instance.getProcessInstanceId());
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(instance.getProcessInstanceId()).singleResult();
            taskInfo.setBusinessKey(historicProcessInstance.getBusinessKey());
            taskInfo.setClaimTime(instance.getClaimTime());
            taskInfo.setCreateTime(instance.getCreateTime());
            taskInfo.setEndTime(instance.getEndTime());
            return taskInfo;
        }).collect(Collectors.toList());
        return taskInfos;
    }

    @ApiOperation(value = "领导审核")
    @PostMapping(value = "/leaderAudit")
    public String leaderAudit(Resolve resolve) {
        if (resolve.getTaskId()==null){
            throw new IllegalArgumentException();
        }
        Map<String,Object> variables = new HashMap<>();
        variables.put("workflow_example_leave_managerAudit_candidateUser","manager");
//        签收
        taskService.claim(resolve.getTaskId(),"manager");
        taskService.complete(resolve.getTaskId(),variables);
        return String.format("ok %s",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }

    @ApiOperation(value = "hr审核")
    @PostMapping(value = "/hrAudit")
    public String hrAudit(Resolve resolve) {
        if (resolve.getTaskId()==null){
            throw new IllegalArgumentException();
        }
        if (ObjectUtils.isEmpty(resolve.getActor())){
            throw new IllegalArgumentException();
        }
        Map<String,Object> variables = new HashMap<>();
        variables.put("workflow_example_leave_managerAudit_candidateUser","manager");
        Task task = taskService.createTaskQuery().taskId(resolve.getTaskId()).singleResult();
        //保存审批意见
        taskService.addComment(resolve.getTaskId(),task.getProcessInstanceId(),"opinion",resolve.getOpinion());
        //保存附件
        taskService.createAttachment("png",resolve.getTaskId(),task.getProcessInstanceId(),"icon.png","attachmentIDs","http://cdn.baidu.com/icon.png");

        taskService.claim(resolve.getTaskId(),resolve.getActor());
        taskService.complete(resolve.getTaskId(),variables);
        return String.format("ok %s",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }

    @ApiOperation(value = "经理审核")
    @PostMapping(value = "/managerAudit")
    public String managerAudit(Resolve resolve) {
        Map<String,Object> variables = new HashMap<>();
        if (resolve.getTaskId()==null){
            throw new IllegalArgumentException();
        }
        if (resolve.getProcessVariable()==null){
            resolve.setProcessVariable("30");
        }
        if (resolve.getProcessVariable().equals("20")){
            variables.put("initiator", "false");
        }
        variables.put("flag",resolve.getProcessVariable());
        taskService.claim(resolve.getTaskId(),"manager");
        taskService.complete(resolve.getTaskId(),variables);
        return String.format("ok %s",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }

    @ApiOperation(value = "重新申请")
    @PostMapping(value = "/restart")
    public String restart(Resolve resolve) {
        if (resolve.getTaskId()==null){
            throw new IllegalArgumentException();
        }
        Map<String,Object> variables = new HashMap<>();
        variables.put("initiator", "");
        taskService.complete(resolve.getTaskId(),variables);
        return String.format("ok %s",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }

    @ApiOperation(value = "进度跟踪")
    @GetMapping(value = "/track")
    public void track(String processInstanceId,HttpServletResponse response) throws IOException {
        //1.获取当前的流程实例
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        String processDefinitionId = null;
        List<String> activeActivityIds = new ArrayList<>();
        List<String> highLightedFlows = new ArrayList<>();
        //2.获取所有的历史轨迹线对象
        List<HistoricActivityInstance> historicSequenceFlows = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId).activityType(BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW).list();
        historicSequenceFlows.forEach(historicActivityInstance -> highLightedFlows.add(historicActivityInstance.getActivityId()));
        //3. 获取流程定义id和高亮的节点id
        if (processInstance != null) {
            //3.1. 正在运行的流程实例
            processDefinitionId = processInstance.getProcessDefinitionId();
            activeActivityIds = runtimeService.getActiveActivityIds(processInstanceId);
        } else {
            //3.2. 已经结束的流程实例
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            processDefinitionId = historicProcessInstance.getProcessDefinitionId();
            //3.3. 获取结束节点列表
            List<HistoricActivityInstance> historicEnds = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(processInstanceId).activityType(BpmnXMLConstants.ELEMENT_EVENT_END).list();
            List<String> finalActiveActivityIds = activeActivityIds;
            historicEnds.forEach(historicActivityInstance -> finalActiveActivityIds.add(historicActivityInstance.getActivityId()));
        }
        //4. 获取bpmnModel对象
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        //5. 生成图片流
        DefaultProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();
        InputStream in = generator.generateDiagram(bpmnModel, "png", activeActivityIds, highLightedFlows, "宋体", "宋体", "宋体", null, 1.0, true);
        ServletOutputStream out = response.getOutputStream();
        IOUtils.copy(in, out);
    }
    @ApiOperation(value = "添加关联")
    @PostMapping("/addRelation")
    public String addRelation() {
        User user = identityService.newUser("zero");
        identityService.saveUser(user);
        Group hrt = identityService.newGroup("HRT");
        identityService.saveGroup(hrt);
        identityService.createMembership("zero","HRT");
        return String.format("ok %s",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));

    }
}
